//
//  smcAsyncConnection.m
//  jaikuAPI
//
//  Created by Christian Martick on 12.04.07.
//  Copyright 2007 Christian Martick. All rights reserved.
//
//	Downloads data from url asynchronously, 
//
//	Copyright (C) 2007 Christian Martick, http://juhu-mac.blogspot.com
//
//	Permission is hereby granted, free of charge, to any person obtaining a copy
//	of this software and associated documentation files (the "Software"), to deal
//	in the Software without restriction, including without limitation the rights
//	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//	copies of the Software, and to permit persons to whom the Software is
//	furnished to do so, subject to the following conditions:
//
//	The above copyright notice and this permission notice shall be included in
//	all copies or substantial portions of the Software.
//
//	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//	THE SOFTWARE.

//  call to start download 
//	- (void) beginDownloadFromURL: (NSURL *) url withTimout: (NSTimeInterval) seconds andUserAgent: (NSString *) agent
//
//	calls delegate if okay
//	- (void) downloadFromURL: (NSURL *) url didFinishWithData: (NSData *)
//
//	and if something went wrong
//	- (void) downloadFromURL: (NSURL *) url didFailWithError: (NSError *) error
//	

#import "smcAsyncConnection.h"


@implementation smcAsyncConnection

//init
- (id) init {//NSLog(@"smcAsyncConnection init");
	self = [super init];
	if (self != nil) {
		 _delegate = nil;
		 theConnection = nil;
		 theURL = nil;
		 error = nil;
		 theInfo = nil;
		 receivedData = [[NSMutableData alloc] init];
	}
	return self;
}

//dealloc clean up
- (void) dealloc {
	[theConnection release];
	[theURL release];
//	[error release];
	[receivedData release];
	[theInfo release];
	[super dealloc];
}

- (void) _callDelegateForFailed 
{
	//something failed, call delegate for failure
	if ([_delegate respondsToSelector:@selector(downloadFromURL:didFailWithError:andInfo:)])
        [_delegate downloadFromURL: theURL didFailWithError: error andInfo: theInfo];
}

- (void) _callDelegateForFinish 
{	
	//everthing okay, call delegate
	if ([_delegate respondsToSelector:@selector(downloadFromURL:didFinishWithData:andInfo:)])
        [_delegate downloadFromURL: theURL didFinishWithData: [NSData dataWithData: receivedData] andInfo: theInfo];
}

//set the delegate
- (void) setDelegate: (id) delegate
{
	_delegate = delegate;
}

//return delegate
- (id) delegate
{
	return _delegate;
}

//begin download
- (BOOL) beginDownloadFromURL: (NSURL *) url withTimout: (NSTimeInterval) seconds userAgent: (NSString *) agent andInfo: (id) info
{//NSLog(@"smcAsyncConnection beginDownloadFromURL:withTimout...");
	//store info, will be added on delegate posts
	[theInfo release];
	theInfo = info;
	[theInfo retain];

	//create the request
	[theURL release];
	theURL = [[NSURL URLWithString: [url absoluteString]] retain];
	NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL: theURL
       cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval: seconds];
	
	if (request == nil)
		return NO;

	//add header field for user agent
	[request addValue: agent forHTTPHeaderField: @"User-Agent"];

	//fire up the connection with self as delegate
	[theConnection release];
	theConnection = [[NSURLConnection alloc] initWithRequest: request delegate: self];
	//NSLog(@"smcAsyncConnection beginDownloadFromURL:withTimout...done");
	return (theConnection != nil);
}

//cancel connection
- (void) cancel
{
	[theConnection cancel];
}

//close the connection
- (void) close
{
	[theConnection cancel];
	[theConnection release];
	theConnection = nil;
}

/*
	the NSURLConnection delegates
*/

// called when the server feels able to respond, e.g. on each redirect etc. so reset data
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{	//NSLog(@"smcAsyncConnection connection:didReceiveResponse:...");
	[receivedData setLength: 0];
	
	//catch http response code from response
	if ([response isKindOfClass: [NSHTTPURLResponse class]])
	{
		//response is http url class
		NSHTTPURLResponse *http = (NSHTTPURLResponse *) response;
		
		//handle status if 200 -> everything okay, else if >= 300, something not right
		
		if ([http statusCode] >= 300)
		{
			//something wrong, report it to error
			error = [NSError errorWithDomain: @"httpURLConnection" code: [http statusCode]  userInfo: [NSDictionary dictionaryWithObjectsAndKeys: 
				theURL, @"url", NULL]];
				
			//cancel connection and call delegate
			[theConnection cancel];
			[self _callDelegateForFailed];
		}
		
	}
	//NSLog(@"smcAsyncConnection connection:didReceiveResponse:...done");
}

//redirection
-(NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse
{ //NSLog(@"smcAsyncConnection connection:willSendRequest:redirectResponse");
	return request;
}

//some data to save
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{//NSLog(@"connection:didReceiveData...");
	[receivedData appendData: data];
//NSLog(@"connection:didReceiveData...done");
}

//no cashing please
-(NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse
{
//NSLog(@"connection:willCacheResponse:,,,");
	return nil;
}

//connection failed
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)anError
{//NSLog(@"connection:didFailWithError");
	//okay, post failure with given error
	
	//don't know why, but theConnection seems to be released at this point
	//so put retain in
	
	[theConnection retain];
	
	error = anError;
	[self _callDelegateForFailed]; 
}

//finished loading
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{		//NSLog(@"smcAsyncConnection connectionDidFinishLoading;");
	//and call delegate	
	[self _callDelegateForFinish];
}

@end
